package ExecuteEngine;

import java.util.List;

import PagedFile.PF_Abort_Exception;
import RecordManagement.*;
import SystemManagement.*;
import parse.*;
import Const.*;
import java.util.*;

public class TableScan extends Operation{
	String tableName;
	public RM_FileHandle fileHandle;
	RM_FileScan fileScan;
	SM_Manager sm;
	List<DataAttrInfo> info;
	List<String> titles;
	RM_Record record;
	Tuple t;
	public RID rid;
	
	public TableScan(String table, SM_Manager sm){
		this.tableName = table;
		this.sm = sm;
		this.t = new Tuple();
		this.info = new ArrayList<DataAttrInfo>();
		this.titles = new ArrayList<String>();
		this.type = Operation.TABLESCAN;
	}
	
	public RC.rc Open(){
		fileHandle = sm.OpenFile(this.tableName);

		info = new ArrayList<DataAttrInfo>();
		
		ScanType st = new ScanType(ScanType.TYPE_STRING, 
				                   Constant.MAXNAME, 0, ScanType.OP_NO,
				                   null, ScanType.PIN_NORMAL);
		
		fileScan = new RM_FileScan(this.fileHandle,st);
		
		sm.GetDataAttrInfo(this.tableName, this.info);
		for(int i=0; i<info.size(); i++)
		    titles.add(Tuple.Trim(info.get(i).attrName));
		
		return RC.rc.SUCCESS;
	}
	
	public boolean hasNext(){
		try{
			record = fileScan.GetNextRec();
			
			if(record != null)
				rid = record.GetRid();
		}
		catch(PF_Abort_Exception e){
			System.out.println("Buffer not enough");
			return false;
		}
		
		if(record == null)
			return false;
		
		return true;
	}
	
	public Tuple GetNext()
	{
	    t = new Tuple();
		for(int i=0; i<info.size(); i++)
			t.tuple.add(new Element(this.tableName, info.get(i).attrName, null));
		
		int position = 0;
		for(int i=0; i<info.size(); i++){
			int length = info.get(i).attrLength;
			
			if(length+position>record.data.length)
			{
				System.out.println("Out of Bounds");
				break;
			}

			byte b[] = new byte[length];
			System.arraycopy(record.data, position, b, 0, length);
			
			if(info.get(i).attrType == ScanType.TYPE_STRING)
				t.tuple.get(i).setValue(new VarcharItem(new StringBuffer(new String(b))));
			else
				t.tuple.get(i).setValue(new IntegerItem(Tuple.BytesToInt(b)));
			
			position += length;
		}
		
		return t;
	}
	
	public void Close(){
		fileScan.CloseScan();
		sm.CloseFile(fileHandle);
	}
	
	public List<String> GetTitles(){
		return titles;
	}
}
